package com.framework.dubbo.producer.utils;

import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.font.*;
import org.apache.pdfbox.pdmodel.graphics.PDXObject;
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
import org.apache.pdfbox.pdmodel.graphics.state.RenderingMode;
import org.apache.pdfbox.text.TextPosition;
import org.fit.pdfdom.BoxStyle;
import org.fit.pdfdom.FontTable;
import org.fit.pdfdom.PDFDomTree;
import org.fit.pdfdom.PDFDomTreeConfig;
import org.w3c.dom.Element;

import java.io.IOException;
import java.util.Iterator;

/**
 * 描述：
 *
 * @author xianggj
 * @Date 2021/10/27 10:17
 **/
public class MYPDFDomTree extends PDFDomTree {

    public MYPDFDomTree() throws IOException {
    }

    public MYPDFDomTree(PDFDomTreeConfig config) throws IOException {
        super(config);
    }

    @Override
    protected void updateStyle(BoxStyle bstyle, TextPosition text) {
        String font = text.getFont().getName();
        String family = null;
        String weight = null;
        String fstyle = null;
        bstyle.setFontSize((float)(Math.round((text.getXScale()-0.5)*100)/100));
        bstyle.setLineHeight(text.getHeight());
        bstyle.setLetterSpacing(0);
        if (font != null) {
            for(int i = 0; i < pdFontType.length; ++i) {
                if (font.toLowerCase().lastIndexOf(pdFontType[i]) >= 0) {
                    weight = cssFontWeight[i];
                    fstyle = cssFontStyle[i];
                    break;
                }
            }

            if (weight != null) {
                bstyle.setFontWeight(weight);
            } else {
                bstyle.setFontWeight(cssFontWeight[0]);
            }

            if (fstyle != null) {
                bstyle.setFontStyle(fstyle);
            } else {
                bstyle.setFontStyle(cssFontStyle[0]);
            }

            String knownFontFamily = this.findKnownFontFamily(font);
            if (!knownFontFamily.equals("")) {
                family = knownFontFamily;
            } else {
                family = this.fontTable.getUsedName(text.getFont());
                if (family == null) {
                    family = font;
                }
            }

            if (family != null) {
                bstyle.setFontFamily(family);
            }
        }

        this.updateStyleForRenderingMode();
    }


    @Override
    protected Element createTextElement(float width) {
        Element el = this.doc.createElement("div");
        el.setAttribute("id", "p" + this.textcnt++);
        el.setAttribute("class", "p");
        String style = this.curstyle.toString();
//        style = style + "width:" + (width+4) + "pt" + ";";
        el.setAttribute("style", style);
        return el;
    }


    private String findKnownFontFamily(String font) {
        String[] var2 = cssFontFamily;
        int var3 = var2.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            String fontFamilyOn = var2[var4];
            if (font.toLowerCase().lastIndexOf(fontFamilyOn.toLowerCase().replaceAll("\\s+", "")) >= 0) {
                return fontFamilyOn;
            }
        }

        return "";
    }

    private void updateStyleForRenderingMode() {
        String fillColor = this.colorString(this.getGraphicsState().getNonStrokingColor());
        String strokeColor = this.colorString(this.getGraphicsState().getStrokingColor());
        if (this.isTextFillEnabled()) {
            this.style.setColor(fillColor);
        } else {
            this.style.setColor("rgba(0,0,0,0)");
        }

        if (this.isTextStrokeEnabled()) {
            this.style.setStrokeColor(strokeColor);
        } else {
            this.style.setStrokeColor("rgba(0,0,0,0)");
        }

    }

    private boolean isTextStrokeEnabled() {
        RenderingMode mode = this.getGraphicsState().getTextState().getRenderingMode();
        return mode == RenderingMode.STROKE || mode == RenderingMode.STROKE_CLIP || mode == RenderingMode.FILL_STROKE || mode == RenderingMode.FILL_STROKE_CLIP;
    }

    private boolean isTextFillEnabled() {
        RenderingMode mode = this.getGraphicsState().getTextState().getRenderingMode();
        return mode == RenderingMode.FILL || mode == RenderingMode.FILL_CLIP || mode == RenderingMode.FILL_STROKE || mode == RenderingMode.FILL_STROKE_CLIP;
    }

    @Override
    protected void updateFontTable() {
        PDResources resources = this.pdpage.getResources();
        if (resources != null) {
            try {
                this.processFontResources(resources, this.fontTable);
            } catch (IOException var3) {
//                log.error("Error processing font resources: Exception: {} {}", var3.getMessage(), var3.getClass());
            }
        }

    }

    /**
     * 去除源码中的多余警告 看着烦
     * @param resources
     * @param table
     * @throws IOException
     */
    private void processFontResources(PDResources resources, FontTable table) throws IOException {
        String fontNotSupportedMessage = "Font: {} skipped because type '{}' is not supported.";
        Iterator var4 = resources.getFontNames().iterator();

        COSName name;
        while(var4.hasNext()) {
            name = (COSName)var4.next();
            PDFont font = resources.getFont(name);
            if (font instanceof PDTrueTypeFont) {
                table.addEntry(font);
//                log.debug("Font: " + font.getName() + " TTF");
            } else if (font instanceof PDType0Font) {
                PDCIDFont descendantFont = ((PDType0Font)font).getDescendantFont();
                if (descendantFont instanceof PDCIDFontType2) {
                    table.addEntry(font);
                } else {
//                    log.warn(fontNotSupportedMessage, font.getName(), font.getClass().getSimpleName());
                }
            } else if (font instanceof PDType1CFont) {
                table.addEntry(font);
            } else {
//                log.warn(fontNotSupportedMessage, font.getName(), font.getClass().getSimpleName());
            }
        }

        var4 = resources.getXObjectNames().iterator();

        while(var4.hasNext()) {
            name = (COSName)var4.next();
            PDXObject xobject = resources.getXObject(name);
            if (xobject instanceof PDFormXObject) {
                PDFormXObject xObjectForm = (PDFormXObject)xobject;
                PDResources formResources = xObjectForm.getResources();
                if (formResources != null && formResources != resources && formResources.getCOSObject() != resources.getCOSObject()) {
                    this.processFontResources(formResources, table);
                }
            }
        }

    }

}
